﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;

namespace GoodStuff.Text
{
    public static class Templating
    {
        /// <summary>
        /// Formats a string using a list of named parameters instead of the standard {0} notation.
        /// </summary>
        /// <param name="format"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public static string FormatCollection(string format, IDictionary<string, object> parameters)
        {
            if (parameters == null)
            {
                return format;
            }
            object[] argList = new object[parameters.Count];
            int i = 0;
            foreach (var item in parameters)
            {
                argList[i] = item.Value;
                // parameter WITH arguments
                format = format.Replace("{" + item.Key + ":", "{" + i.ToString() + ":");
                // parameter WITHOUT arguments
                format = format.Replace("{" + item.Key + "}", "{" + i.ToString() + "}");

                i++;

            }

            try
            {
                string tmp = string.Format(format, argList);

                int pos;
                while((pos = tmp.IndexOf("[WHEN:False]")) >= 0)
                {
                    int pos2 = tmp.IndexOf("[/WHEN]", pos);
                    if (pos2 < 0)
                    {
                        throw new FormatException("Missing [/WHEN] in template.");
                    }

                    //remove all character between pos and pos2.
                    tmp = tmp.Substring(0, pos) + tmp.Substring(pos2 + "[/WHEN]".Length);
                }

                tmp = tmp.Replace("[WHEN:True]", "");
                tmp = tmp.Replace("[/WHEN]", "");

                //remove [WHEN:false]....[/WHEN]
                //en
                //remove [/WHEN:true] en [/WHEN]

                return tmp;
            }
            catch (FormatException fe)
            {
                throw new FormatException("One or more placeholders were not filled.\n\n" + format, fe);
            }
        }

        public static string FormatFromFile(string filename, System.Globalization.CultureInfo culture, IDictionary<string, object> parameters)
        {
            string template = ReadLocalizedContent(filename, culture);
            return FormatCollection(template, parameters);
        }

        private static string ReadLocalizedContent(string filename, System.Globalization.CultureInfo culture)
        {
            bool invariantCulture = false;

            while (invariantCulture == false)
            {
                if (culture == System.Globalization.CultureInfo.InvariantCulture)
                {
                    invariantCulture = true;
                }

                string localizedFilename;

                if (invariantCulture)
                {
                    //changeextension maintains the path part etc.
                    localizedFilename = System.IO.Path.ChangeExtension(filename,
                        string.Concat(".", culture.Name, System.IO.Path.GetExtension(filename)));
                }
                else
                {
                    //no need to inject the culture ID.
                    localizedFilename = filename;

                }

                //try to open the file. If that fails, go to the parent culture iteratively.
                if (System.IO.File.Exists(localizedFilename))
                {
                    using (FileStream s = new FileStream(localizedFilename, FileMode.Open, FileAccess.Read))
                    {
                        using (StreamReader r = new StreamReader(s, Encoding.UTF8))
                        {
                            return r.ReadToEnd();
                        }
                    }               
                }

                culture = culture.Parent;
            }

            throw new System.IO.FileNotFoundException("A message template file could not be found. File : " + filename, filename);
        }       
    }
}
